<!--
 * @Author: ZJP 2712104231@qq.com
 * @Date: 2025-02-17 09:45:37
 * @LastEditors: ZJP 2712104231@qq.com
 * @LastEditTime: 2025-03-10 09:47:15
 * @FilePath: \zhlx-autoform-ui\src\components\form-table\index.vue
 * @Description: 介绍文件的作用
 * 
 * Copyright (c) 2025 by zhlx - 2712104231@qq.com, All Rights Reserved. 
-->
<template>
  <div id="commonTable">
      <el-row class="batch-import-options-row options-row">
        <div>
          <el-button @click="batchDeleteSubFormAllRow"><el-icon>
            <Delete />
          </el-icon>删除全部</el-button>
          <el-button :disabled="!this.selectionList.length" @click="batchDeleteSubFormRow"><el-icon>
            <Delete />
          </el-icon>删除</el-button>
          <el-button @click="onclickSetting">
              <el-icon><Setting /></el-icon>设置
          </el-button>

          <el-radio-group class="date-type" v-model="dataType" @change="onchangeDataType">
          <el-radio :value="0">全部数据</el-radio>
          <el-radio :value="1">问题数据</el-radio>
        </el-radio-group>
        </div>
        <el-input
          v-model="tableHeadKeyword"
          style="width: 300px;"
          :disabled="!selectTableHeadId"
          :placeholder="placeholderText"
        >
          <template #prepend>
            <el-select v-model="selectTableHeadId" placeholder="请选择" class="select-table-head-id">
              <el-option label="全部" />
              <el-option :label="filterSpecialCharByLabel(subWidget.options.label)" :value="subWidget.options.name" v-for="subWidget in columns" :key="subWidget.options.name" />
            </el-select>
          </template>
          <!-- <template #append>
            <el-button :icon="Search" @click="onclickTableHeadSearch" />
          </template> -->
        </el-input>
      </el-row>
      <div class="custom-table">
        <el-table v-if="data" :data="pageData" :height="height" :max-height="maxHeight" border stripe tooltip-effect="light"
                @selection-change="handleSelectionChange" :size="tableSize" :style="{width: tableWidth}">
          <el-table-column  type="selection" width="45" fixed="left"></el-table-column>
          <template v-for="(column, index) in columns" :key="index">
            <el-table-column
              :prop="column.options.name"
              :label="column.options.label"
              :align="column.align ? column.align:'center'"
              :width="getColumnWidth(column)"
              :show-overflow-tooltip="false"
              :fixed="column.options.name.includes('unique-') ? 'left' : false"
              class="custom-table-column"
            >
            <template #header="{column}">
              <span><span v-if="showRequired(column.property)" style="color: red;">*</span>{{ filterSpecialCharByLabel(column.label) }}</span>
            </template>
            <template #default="scope">
              <template v-if="scope.row[column.options.name] && scope.row[column.options.name][0]">
                <el-input 
                  v-if="['input', 'serial-number', 'textarea', 'number'].includes(column.type)" 
                  v-model="scope.row[column.options.name][0].defaultValue"
                  :type="['textarea', 'number'].includes(column.type) ? column.type : 'text'"
                  @input="onchange(column, scope.row)"></el-input>
                <el-time-picker 
                  v-else-if="['time', 'time-range'].includes(column.type)" 
                  v-model="scope.row[column.options.name][0].defaultValue" 
                  :format="column.options.format"
                  :is-range="column.type === 'time-range'"
                  value-format="HH:mm:ss" 
                  placeholder="选择时间"
                  @change="onchangeTime($event, column, scope.row)" />
                <el-date-picker
                  v-else-if="['date', 'date-range'].includes(column.type)"
                  v-model="scope.row[column.options.name][0].defaultValue"
                  :type="column.options.type"
                  :clearable="column.options.clearable" :editable="column.options.editable"
                  :format="column.options.format" :value-format="column.options.valueFormat" :time-format="column.options.format.split(' ')[1]"
                  placeholder="选择日期"
                  :disabled-date="date => disabledDate(date, column.options.limitStartDate, column.options.limitEndDate)"
                  @change="onchangeDate($event, column, scope.row)" />
                <el-select 
                  v-else-if="['radio', 'checkbox', 'select', 'switch', 'rate', 'slider'].includes(column.type)" 
                  v-model="scope.row[column.options.name][0].defaultValue"
                  :multiple="getMultiple(column)"
                  @change="onchange(column, scope.row)">
                  <template v-if="['switch'].includes(column.type)">
                    <el-option :label="column.options.activeText || '开'" :value="true"></el-option>
                    <el-option :label="column.options.inactiveText || '关'" :value="false"></el-option>
                  </template>
                  <template v-else-if="['rate'].includes(column.type)">
                    <el-option v-for="option in column.options.max" :key="option" :label="option + '星'" :value="option"></el-option>
                  </template>
                  <template v-else-if="['slider'].includes(column.type)">
                    <el-option v-for="option in (column.options.max / column.options.step)" :key="option" :label="(option * column.options.step) + '%'" :value="option * column.options.step"></el-option>
                  </template>
                  <template v-else-if="['select'].includes(column.type)">
                    <el-option v-for="option in column.options.optionItems" :label="option.label" :value="option.value?.toString()" :key="option.value"></el-option>
                  </template>
                  <template v-else>
                    <el-option v-for="option in column.options.optionItems" :label="option.label" :value="option.value" :key="option.value"></el-option>
                  </template>
                </el-select>
                <el-input 
                  v-else-if="['select-department', 'select-group', 'select-role', 'select-person', 'select-post', 'select-relativePost'].includes(column.type)"
                  :value="getBusinessSelectValue(column, scope.row)">
                  <template #append>
                    <el-icon size="16" @click="onclickBusinessSelect(column, scope.row)">
                      <el-icon-edit></el-icon-edit>
                    </el-icon>
                  </template>
                </el-input>
                <!-- showError(column, scope.row) -->
                <template v-if="scope.row[column.options.name][0].errorMessage">
                  <el-tooltip
                    effect="light"
                    :content="scope.row[column.options.name][0].errorMessage"
                    placement="top-end"
                  >
                    <el-icon class="warning-icon" size="24" color="#f56c6c"><WarningFilled /></el-icon>
                  </el-tooltip>
                </template>
              </template>
            </template>
            </el-table-column>
          </template>
          <slot name="table_operation"/>
        </el-table>
      </div>
      <div class="footer">
        <div class="tongji">共<span style="color: #f56c6c;">{{allErrorNumber}}</span>条错误，当前表共<span style="color: #f56c6c;">{{errorList.length}}</span> 条错误，请点击数值手工修改调整！</div>
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          style="text-align: right;margin:0;"
          :current-page="pagination.pageNo"
          :page-size="pagination.limit"
          :page-sizes="pagination.sizes"
          :total="filterData.length"
          layout="total, sizes, prev, pager, next, jumper">
      </el-pagination>
      </div>
  </div>
  <ZHLXCommonSelect 
    v-if="field"
    ref="zhlxCommonSelectRef"
    title="组选择" 
    :show-input="false"
    :model-value="row[field.options.name][0].defaultValue" 
    :placeholder="field.options.placeholder"
    :multiple="field.options.multiple"
    :clearable="field.options.clearable" 
    :authorityList="field.options.authorityList"
    :selectType="field.options.selectType"
    :choosePerson="field.options.choosePerson" 
    :isReturnData="field.options.isReturnData"
    @close="oncloseZHLXCommonSelect"
		@ok="onchangeZHLXCommonSelect" />

  <el-dialog
    title="高级设置"
    v-model="settingDialogVisible"
    :show-close="false"
    append-to-body
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :destroy-on-close="true">
    <el-form>
      <el-form-item label="修改数据后，您是想：" label-position="top">
        <el-radio-group v-model="settingObj.modifyRanges">
          <el-radio :value="0">仅修改此单元格中数据</el-radio>
          <el-radio :value="1">自动同步修改该列其他相同的数据</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>

    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="settingDialogVisible = false">
          确定
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script>
  import { Search, WarningFilled } from '@element-plus/icons-vue'
  import ZHLXCommonSelect from '@/components/ZHLX-Components/common/commonSelect/index2.vue' // 选人组件
  import { deepClone } from '@/utils/util';
  export default {
    name: 'VTable',
    components: {
      ZHLXCommonSelect,
    },
    props: {
      tableWidth: [String, Number],
      columns: Array,
      data: Array,
      errorList: {
        type: Array,
        default: () => []
      },
      showPager: {
        type: Boolean,
        default: true
      },
      showCheckBox: {
        type: Boolean,
        default: true
      },
      height: {
        type: String,
        default: "100%"
      },
      maxHeight: {
        type: Number,
        default: '100%'
      },
      tableSize: {
        type: String,
        default: 'default'
      },
      allErrorNumber: {
        type: Number,
        default: 0
      }
    },
    data() {
      return {
        Search,
        WarningFilled,
        field: null,
        row: null,
        selectionList: [],
        dataType: 0, // 数据类型
        tableHeadKeyword: '',
        selectTableHeadId: undefined,
        settingDialogVisible: false,
        settingObj: { // 高级设置配置
          modifyRanges: 0 // 修改范围，0当前单元格，1同列相同数据所有单元格
        },
        pagination: {
          pageNo: 1,
          limit: 10,
          total: 0,
          sizes: [10, 20, 50, 100],
        },
      }
    },
    computed: {
      filterData(){
        let data = deepClone(this.data)
        if (this.dataType === 1) {
          data = data.filter(row => this.errorList.findIndex(errItem => errItem.index === row.index) !== -1)
        }
        if(this.tableHeadKeyword) {
          data = data.filter(row => {
            return this.isKeywordMatch(row, this.selectTableHeadId, this.tableHeadKeyword)
          })
        }
        return data
      },
      pageData() {
        const pagination = this.pagination
        const start = (pagination.pageNo - 1) * pagination.limit
        const end = start + pagination.limit
        return this.filterData.slice(start, end)
      },

      placeholderText() {
        if (this.selectTableHeadId) {
          const widget = this.columns.find(item => item.options.name === this.selectTableHeadId)
          if (['date-range'].includes(widget.type)) {
            return `格式：1999-01-01~2025-01-01`
          } else if (['time-range'].includes(widget.type)) {
            return `格式：08:00:00~23:59:59`
          }
        }
        return '请输入关键字检索'
        
      },
    },
    watch: {
      filterData: {
        handler(val) {
          this.pagination.total = val?.length || 0
        },
        immediate: true
      },
      pageData: {
        handler(val) {
          console.log('pageData change', val)
        },
        immediate: true
      }
    },
    methods: {
      // 过滤特殊字符
      filterSpecialCharByLabel(str) {
        if (typeof str === 'string') return str = str.replaceAll(/<br>/g, '')
        return str
      },
      /**
       * 日期选择器 设置可选范围
       * @param {*} date date-picker的每一项
       * @param {*} limitStartDate 限制开始日期
       * @param {*} limitEndDate 限制结束日期
       */
       disabledDate(date, limitStartDate, limitEndDate) {
        return date.setHours(0, 0, 0, 0) < (new Date(limitStartDate).setHours(0, 0, 0, 0)) || date.setHours(0, 0, 0, 0) > new Date(limitEndDate).setHours(0, 0, 0, 0)
      },
      showRequired(curColumn) {
        const findColumn = this.columns.find(column => column.options.name === curColumn)
        return findColumn && findColumn.options.required
      },
      getBusinessSelectValue(column, row) {
        if (column.options.multiple) {
          // console.log('row[column.options.name][0]',row[column.options.name])
          return row[column.options.name][0]?.defaultValue?.map(item => item.mainName).join('、')
        }
        return row[column.options.name][0]?.defaultValue?.mainName
      },
      getColumnWidth(column) {
        if (['time', 'date'].includes(column.type)) {
          return 260
        } else if (['time-range', 'date-range'].includes(column.type)) {
          return 420
        } else if(['select-department', 'select-group', 'select-role', 'select-person', 'select-post', 'select-relativePost'].includes(column.type)) {
          return 300
        }
        return 200
      },
      batchDeleteSubFormAllRow() {
        this.$confirm(`确定删除所选数据吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$emit('all-row-remove')
        })
      },
      batchDeleteSubFormRow() {
        if (this.selectionList.length === 0) {
          this.$message.info('请选择要删除的记录！')
          return
        }
        this.$confirm(`确定删除所选数据吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$emit('rows-remove', this.selectionList)
        })
      },
      onclickSetting() {
        this.settingDialogVisible = true
      },
      onchangeDataType() {
        
      },
      onchangeTime(e, column, row) {
        row[column.options.name][0].defaultValue = e
        this.onchange(column, row)
      },
      onchangeDate(e, column, row) {
        let timestampList = []
        if(column.options.valueFormat !== "x") {
          let valList = e ? Array.isArray(e) ? e : [e] : []
          valList.forEach(item => {
            if (!item) return;
            item = item.replace(/(年)|(月)/g, '-')
            item = item.replace(/(时)|(分)/g, ':')
            item = item.replace(/(日)|(秒)/g, '')
            const timestamp = new Date(item).getTime();
            timestampList.push(timestamp)
          })
        } else {
          timestampList = e ? Array.isArray(e) ? e : [e] : []
        }
        row[column.options.name][0].defaultValue = column.type === 'date-range' ? timestampList : timestampList[0]
        this.onchange(column, row)
      },
      onchange(column, row) {
        this.$emit('field-change', column, row, this.settingObj.modifyRanges)
        // this.$nextTick(() => {
        //   this.$emit('validate', column, row)
        // })
      },
      isKeywordMatch (item, itemKey, keyword) {
        const widgetList = this.columns
        const widget = widgetList.find(item => item.options.name === itemKey)
        if(['input','textarea', 'serial-number'].includes(widget.type)) {
          return (item[itemKey][0].defaultValue + '').includes(keyword)
        } else if (['number'].includes(widget.type)) {
          return (item[itemKey][0].defaultValue + '') === keyword
        } else if (['date', 'date-range', 'time', 'time-range'].includes(widget.type)) {
          return (item[itemKey][0].zhlx_gjz_label + '').includes(keyword)
        } else if(['radio', 'checkbox', 'select'].includes(widget.type)) {
          const optionItems = widgetList.find(item => item.options.name === itemKey).options
          .optionItems
          if (['radio'].includes(widget.type) || (['select'].includes(widget.type) && !widget.options.multiple)) {
            return optionItems.find(opt => opt.value == item[itemKey][0].defaultValue)?.label.includes(keyword)
          }
          const selectopt = item[itemKey][0].defaultValue.map(item => optionItems.find(opt => opt.value == item)?.label)
          return selectopt.join(',').includes(keyword)
        } else if (['select-relativePost', 'select-department', 'select-role', 'select-person', 'select-post', 'select-group'].includes(widget.type)) {
          if (widget.options.multiple) {
            const mainNames = item[itemKey][0].defaultValue.map(value => value.mainName).join('、')
            return mainNames.includes(keyword)
          } else {
            return item[itemKey][0].defaultValue.mainName.includes(keyword)
          }
        } else if(['rate'].includes(widget.type)) {
          return (item[itemKey][0].defaultValue + '星').includes(keyword)
        } else if(['slider'].includes(widget.type)) {
          return (item[itemKey][0].defaultValue + '%').includes(keyword)
        } else if (['switch'].includes(widget.type)) {
          return (item[itemKey][0].defaultValue ? (widget.options.activeText || '开') : (widget.options.inactiveText || '关')).includes(keyword)
        }
        this.$message.info('暂不支持此类型数据！')
        return true
      },
      showError(column, row) {
        return this.errorList.find(item => item.options.name === column.options.name && item.index === row.index)
      },
      getMultiple(column) {
        if (['radio', 'switch'].includes(column.type)) {
          return false;
        } else if (column.type === 'checkbox') {
          return true;
        }
        return column.options.multiple;
      },
      onclickBusinessSelect(column, row) {
        this.field = deepClone(column);
        this.row = deepClone(row);
        this.$nextTick(() => {
          this.$refs.zhlxCommonSelectRef.openDialog();
        });
      },
      oncloseZHLXCommonSelect() {
        this.field = null;
        this.row = null;
      },
      onchangeZHLXCommonSelect(ids, records) {
        this.row[this.field.options.name][0].defaultValue = this.field.options.multiple ? records : (records[0] || "");
        this.onchange(this.field, this.row)
      },
      handleSelectionChange(val) {
        this.selectionList = val;
        // this.$emit('handleSelectionChange', val);
      },
      handleSizeChange(val) {
        this.pagination.limit = val;
        // this.$emit('handleSizeChange', val);
      },
      handleCurrentChange(val) {
        this.pagination.pageNo = val;
        // this.$emit('handleCurrentChange', val);
      },
    }
  }
</script>

<style lang="scss" scoped>
#commonTable {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  .options-row {
    display: flex;
    justify-content: space-between;
    margin-bottom: 8px;
    .date-type {
      margin-left: 16px;
    }
    
    .select-table-head-id {
      width: 100px;
      :deep(.el-select__wrapper) {
        box-shadow: none;
      }
    }
  }
  .custom-table {
    flex: 1;
    overflow: hidden;
  }
  .footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 0;
    .tongji {
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}
.el-table {
  // 解决table组件内容滚动时页面滚动条同步滚动
  overflow: auto;
  // 必须设置
  position: relative;

  :deep(.el-table__fixed-header-wrapper) thead th > .cell {
    white-space: nowrap !important;  /* 禁止表头换行 */
  }

  :deep(.el-table__header-wrapper) thead th > .cell {
    white-space: nowrap !important;  /* 禁止表头换行 */
  }
  :deep(.el-table__cell) {
    position: relative;
    .warning-icon {
      position: absolute;
      right: 4px;
      top: 50%;
      transform: translateY(-50%);
      z-index: 1111;
    }
  }
}
</style>
